package com.edushare.common.dao;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;

import org.apache.cayenne.exp.Expression;
import org.apache.cayenne.query.SelectQuery;
import org.apache.cayenne.query.SortOrder;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.edushare.common.orm.ORMInterface;
import com.edushare.common.vo.Poll;
import com.edushare.common.vo.PollOptions;
import com.edushare.common.vo.PollPages;
import com.edushare.common.vo.PollQuestions;
import com.edushare.common.vo.UserPoll;
import com.edushare.common.vo.Users;

public class PollsDAO extends CayenneBasedDAO {

	private static final Log log = LogFactory.getLog(PollsDAO.class);

	public PollsDAO(ORMInterface ormInterface) {
		super(ormInterface);
	}

	public Poll getPollById(Integer id) {
		Expression exp = Expression.fromString("pollId = $id");
		HashMap<String, Integer> hm = new HashMap<String, Integer>();
		hm.put("id", id);

		SelectQuery query = new SelectQuery(Poll.class, exp
				.expWithParameters(hm));
		List p = getDataContext().performQuery(query);
		if (p.size() > 0)
			return (Poll) p.get(0);
		return null;
	}

	public Poll createNewPoll() {
		Poll poll = new Poll();
		poll.setParentPoll(null);
		poll.setStatus(Poll.POLL_STATUS_DRAFT);
		getDataContext().registerNewObject(poll);
		getDataContext().commitChanges();
		addNewPage(poll, "New Page", 1);
		return poll;
	}

	public Poll createNewPoll(Poll parent) {
		Poll poll = new Poll();
		poll.setParentPoll(parent);
		poll.setPollAnonymous(parent.getPollAnonymous());
		poll.setPollDesc(parent.getPollDesc());
		poll.setPollEndDate(parent.getPollEndDate());
		poll.setPollName(parent.getPollName());
		poll.setPollResultsPublic(parent.getPollResultsPublic());
		poll.setStatus(parent.getStatus());
		poll.setPollStartDate(parent.getPollStartDate());
		poll.setCreator(parent.getCreator());
		getDataContext().registerNewObject(poll);
		getDataContext().commitChanges();
		addNewPage(poll, "New Page", 1);
		return poll;
	}

	public void deletePoll(Poll p) {
		if(p.getChildrenPolls().size() > 0){
			Poll firstChild = p.getChildrenPolls().get(0);
			if(p.getChildrenPolls().size() > 1){
				List<Poll> children = new ArrayList<Poll>(p.getChildrenPolls());
				for(int i=1;i<children.size();i++){
					Poll currChild = children.get(i);
					p.removeFromChildrenPolls(currChild);
					currChild.setParentPoll(firstChild);
				}
			}
			p.removeFromChildrenPolls(firstChild);
			firstChild.setParentPoll(null);
		}
		getDataContext().commitChanges();
		
		getDataContext().deleteObjects(p.getUserPoll());
		List<PollQuestions> pqList = p.getQuestions();
		for (PollQuestions pq : pqList) {
			getDataContext().deleteObjects(pq.getAnswers());
			getDataContext().deleteObjects(pq.getOptions());
		}
		getDataContext().deleteObjects(pqList);
		getDataContext().deleteObjects(p.getPages());
		getDataContext().deleteObject(p);
		getDataContext().commitChanges();
	}

	public PollQuestions addQuestionToPoll(Poll poll, String question,
			int required, Integer questionType, PollPages page, Integer sNo) {
		List<PollQuestions> pqList = poll.getQuestions();
		for (PollQuestions p : pqList) {
			if (p.getQuestionSerialNo() >= sNo) {
				p.setQuestionSerialNo(p.getQuestionSerialNo() + 1);
			}
		}
		PollQuestions newQuestion = new PollQuestions();
		newQuestion.setPoll(poll);
		newQuestion.setRequired(required);
		newQuestion.setPage(page);
		newQuestion.setQuestion(question);
		newQuestion.setQuestionType(questionType);
		newQuestion.setQuestionSerialNo(sNo);
		getDataContext().registerNewObject(newQuestion);
		getDataContext().commitChanges();
		return newQuestion;
	}

	public PollPages addNewPage(Poll poll, String pageName, int sNo) {
		List<PollPages> pageList = poll.getPages();
		for (PollPages p : pageList) {
			if (p.getPageNumber() >= sNo) {
				p.setPageNumber(p.getPageNumber() + 1);
			}
		}
		PollPages newPage = new PollPages();
		newPage.setPageNumber(sNo);
		newPage.setPageTitle(pageName);
		newPage.setPoll(poll);
		getDataContext().registerNewObject(newPage);
		getDataContext().commitChanges();
		return newPage;
	}

	public void deletePage(PollPages page) {
		List<PollPages> pageList = page.getPoll().getPages();
		for (PollPages p : pageList) {
			if (p.getPageNumber() >= page.getPageNumber())
				p.setPageNumber(p.getPageNumber() - 1);
		}
		
		List<PollQuestions> allQuestions = page.getPoll().getQuestions();
		List<PollQuestions> pqList = page.getQuestions();
		for(PollQuestions pq:pqList){
			clearOptions(pq);
			for(PollQuestions all:allQuestions){
				if (all.getQuestionSerialNo() > pq.getQuestionSerialNo()) {
					all.setQuestionSerialNo(all.getQuestionSerialNo() - 1);
				}
			}
		}

		getDataContext().deleteObjects(pqList);
		getDataContext().deleteObject(page);
		getDataContext().commitChanges();
	}

	public void addMultipleOptionsToPoll(PollQuestions question,
			String[] options) {
		int i = 0;
		for (i = 0; i < options.length; i++) {
			PollOptions po = new PollOptions();
			po.setOptionString(options[i]);
			po.setQuestion(question);
			po.setSerialNo(i);
			getDataContext().registerNewObject(po);
		}
		getDataContext().commitChanges();
	}

	public void clearOptions(PollQuestions q) {
		List<PollOptions> options = q.getOptions();
		getDataContext().deleteObjects(options);
		getDataContext().commitChanges();
	}

	public void deleteQuestion(PollQuestions pq) {
		clearOptions(pq);
		Poll p = pq.getPoll();
		List<PollQuestions> pqList = p.getQuestions();
		for (PollQuestions temp : pqList) {
			if (temp.getQuestionSerialNo() > pq.getQuestionSerialNo()) {
				temp.setQuestionSerialNo(temp.getQuestionSerialNo() - 1);
			}
		}
		getDataContext().deleteObject(pq);
		getDataContext().commitChanges();
	}

	public void addUsersToPoll(List<Users> userList) {

	}

	@SuppressWarnings("unchecked")
	public List<Poll> getPollsByCreator(Integer creatorType, Integer creatorId) {
		Expression exp = Expression
				.fromString("pollGroupType = $pgt and pollGroupId = $pgi");
		HashMap<String, Integer> hm = new HashMap<String, Integer>();
		hm.put("pgt", creatorType);
		hm.put("pgi", creatorId);

		SelectQuery query = new SelectQuery(Poll.class, exp
				.expWithParameters(hm));
		query.addOrdering("pollEndDate", SortOrder.DESCENDING);
		return (List<Poll>) getDataContext().performQuery(query);
	}

	public PollQuestions getQuestionBySNo(Poll p, int sNo) {
		List<PollQuestions> pqList = p.getQuestions();
		for (PollQuestions pq : pqList) {
			if (pq.getQuestionSerialNo() == sNo)
				return pq;
		}
		return null;
	}

	public PollOptions getPollOptionsById(int pk) {
		PollOptions p = null;
		Expression exp = Expression.fromString("optionId = $optionId");
		HashMap<String, Integer> params = new HashMap<String, Integer>();
		params.put("optionId", pk);
		SelectQuery query = new SelectQuery(PollOptions.class, exp
				.expWithParameters(params));
		List lst = getDataContext().performQuery(query);
		if (lst != null && lst.size() > 0)
			p = (PollOptions) lst.get(0);
		return p;
	}

	public List<Poll> getPollsByCreator(Users user) {
		return user.getCreatedPolls();
	}

	public List<Poll> getPollsByUser(Users user) {
		List<Poll> pollList = new ArrayList<Poll>();
		List<UserPoll> pList = user.getRequestedPolls();
		for (UserPoll p : pList) {
			pollList.add(p.getPoll());
		}
		return pollList;
	}

	public void commit() {
		getDataContext().commitChanges();
	}

	public List<Poll> getAllRelatedPolls(Poll poll) {
		List<Poll> pollList = new ArrayList<Poll>();
		if (poll.getParentPoll() == null) {
			pollList.add(poll);
			pollList.addAll(poll.getChildrenPolls());
		} else {
			Poll parent = poll.getParentPoll();
			pollList.add(parent);
			pollList.addAll(parent.getChildrenPolls());
		}
		return pollList;
	}

	public void copyPollQuestions(Poll destPoll, Poll sourcePoll) {
		List<PollOptions> del1 = new ArrayList<PollOptions>();
		List<PollQuestions> del2 = destPoll.getQuestions();
		List<PollPages> del3 = destPoll.getPages();

		for (PollQuestions pq : del2) {
			del1.addAll(pq.getOptions());
		}

		getDataContext().deleteObjects(del1);
		getDataContext().deleteObjects(del2);
		getDataContext().deleteObjects(del3);
		getDataContext().commitChanges();

		List<PollPages> pages = sourcePoll.getPages();
		for (PollPages page : pages) {
			PollPages newPage = new PollPages();
			getDataContext().registerNewObject(newPage);
			newPage.setPageNumber(page.getPageNumber());
			newPage.setPageTitle(page.getPageTitle());
			destPoll.addToPages(newPage);
			

			List<PollQuestions> questions = page.getQuestions();
			for (PollQuestions q : questions) {
				PollQuestions newQ = new PollQuestions();
				getDataContext().registerNewObject(newQ);
				newQ.setPage(newPage);
				newQ.setPoll(destPoll);
				newQ.setQuestion(q.getQuestion());
				newQ.setQuestionSerialNo(q.getQuestionSerialNo());
				newQ.setQuestionType(q.getQuestionType());
				newQ.setRequired(q.getRequired());
				
				List<PollOptions> poList = q.getOptions();
				for (PollOptions po : poList) {
					PollOptions newO = new PollOptions();
					newO.setOptionString(po.getOptionString());
					newO.setQuestion(newQ);
					newO.setSerialNo(po.getSerialNo());
					getDataContext().registerNewObject(newO);
				}
			}
		}
		getDataContext().commitChanges();
	}
}
